package br.com.afi.pattern.wrapper;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import br.com.afi.pattern.converter.Converter;
import br.com.afi.pattern.model.Model;
import br.com.afi.pattern.vo.ValueObject;

/**
 * Essa classe encapsula uma lista {@link Model} ou uma lista de {@link ValueObject}, e provê a
 * conversão entre as duas listas.
 * 
 * @author André de Fontana Ignacio
 * @param <E> Tipo do Model (Entity)
 * @param <V> Tipo do Value Object
 */
public class WrapperList<E extends Model<? extends Serializable>, V extends ValueObject> implements Serializable
{
	private static final long serialVersionUID = -3492459468898400969L;

	private Converter<E, V> converter;
	private List<E> models;
	private List<V> vos;

	/**
	 * Construtor
	 * 
	 * @param models Lista de Models (Entity)
	 * @param converter Conversor (Ideal que seja Singleton).
	 * @param model Model?
	 */
	public WrapperList( List<E> models, Converter<E, V> converter, boolean model )
	{
		super();
		this.models = models;
		this.converter = converter;
	}

	/**
	 * Construtor
	 * 
	 * @param vos Lista de Value Object
	 * @param converter Conversor (Ideal que seja Singleton).
	 */
	public WrapperList( List<V> vos, Converter<E, V> converter )
	{
		super();
		this.vos = vos;
		this.converter = converter;
	}

	/**
	 * Obtém a lista como uma lista de Models.
	 * 
	 * @return Value Object
	 */
	public List<E> asModelList()
	{
		return models != null ? models : converter.convertListForward( vos );
	}

	/**
	 * Obtém a lista como uma lista de Value Objects.
	 * 
	 * @return Value Object
	 */
	public List<V> asVOList()
	{
		return vos != null ? vos : converter.convertListReverse( models );
	}

	/**
	 * Obtém a lista com uma lista de Wrappers
	 * 
	 * @return Lista de Wrappers
	 */
	public List<Wrapper<E, V>> asList()
	{
		final List<Wrapper<E, V>> list = new ArrayList<Wrapper<E, V>>();
		if ( models != null && vos != null )
		{
			final Iterator<E> itModel = models.iterator();
			final Iterator<V> itVO = vos.iterator();

			while ( itModel.hasNext() )
			{
				list.add( new Wrapper<E, V>( itModel.next(), itVO.next(), converter ) );
			}
		}
		else if ( models != null )
		{
			for ( E e : models )
			{
				list.add( new Wrapper<E, V>( e, converter ) );
			}
		}
		else if ( vos != null )
		{
			for ( V v : vos )
			{
				list.add( new Wrapper<E, V>( v, converter ) );
			}
		}
		return list;
	}
}
